package com.fingard.dsp.bank.directbank.gynsh01.util;

import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.bouncycastle.util.encoders.Base64;

public class SecurityUtils {
	/**
	 * 银行公钥

	private static final String publicKey_bank = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+Clsw4jpxXOyOWa9oRqBGl+EHYfpxu2PLvmOgtRE+tMD5vLP06exaW6weicsM7pXMg47nX90YZsREiPmJWh6SA/FbefZoCrEnIdogJ3URGjN4MAycf8ugdSEjeUXmr4AXf3kmm+dlDF5LseBUFK36rOeN6/nX2Y1rCLRc6XjEIQIDAQAB";
     */
     /**
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";
    
    /** 
     *  签名算法
     */
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
 
    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;
    /** 
     * 用商户私钥签名
     * 
     * @param data
     * 
     * @return
     * @throws Exception
     */
    public static String signByMerchantPrivateKey(byte[] data,String privateKey_merchant) throws Exception {
        byte[] keyBytes = Base64.decode(privateKey_merchant.getBytes());
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateK);
        signature.update(data);
        return new String(Base64.encode(signature.sign()));
    }
 
    /** 
     * 用银行公钥来验证签名
     * 
     * @param data 已加密数据
     * @param signed 数字签名
     * 
     * @return
     * @throws Exception
     * 
     */
    public static boolean verifyByBankPublicKey(byte[] data, String signed,String publicKeyBank)
            throws Exception {
        byte[] keyBytes = Base64.decode(publicKeyBank.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicK);
        signature.update(data);
        return signature.verify(Base64.decode(signed));
    }
 
    /** 
     * 银行公钥加密
     * 
     * @param data 源数据
     * @return
     * @throws Exception
     */
    public static String encryptByBankPublicKey(byte[] data,String publicKeyBank)
            throws Exception {
        byte[] keyBytes = Base64.decode(publicKeyBank.getBytes());
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return new String(Base64.encode(encryptedData));
    }
 
    /** 
           * 商户私钥解密
     * 
     * @param data 源数据
     * @return
     * @throws Exception
     */
    public static String decryptByMerchantPrivateKey(byte[] data,String privateKeyMerchant)
            throws Exception {
        privateKeyMerchant = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKtf1JxUAR8HcW23a8fkjk7rYqtJ9ZKwW1CqS3vdMhoMCo8n9kVmNvZtoCFi+x5eOOtK9iYyLHXOQzVDnB3PhgfqPccUKpPgpfw9EC8sMV1ZKGz9lNBNNVEFNTupheIzMR7728vFbNMQjBCzdFkinULW5wynDMX2+FUUdkKbuOO1AgMBAAECgYBcmNwVV+J/NJNaWBg5mso15EOdD8pL51R/wnQkykDvCACQl2Qe3XrnLhau03+iSgDxScC0pLmXMcrotc5d4Sqmq65FsBFtvOKz9HtV5Frd95Ojvdf5uaQbZMHqiIOiriSZvmgUC6ZE5uoY1EFvEjVzUqZ7TfQUc1xXq5pzm0q+IQJBANlYnS9b3W8Ldz3IxTHBL147nd+4JXbNCGgrWdndWe9GzY9cavRgM3rFRv72MwBCUXv8QXgNx3tLSM9I4qN2rMkCQQDJ2jODfeWOMVGNLr6dcOhOrFPqxh857app428e+IRR1HFXbrJb34Axl3Oi94Gjonsjr58Wn32qp3AM+Z4+33GNAkBaqdZXzRBfo/7HrRplGNrzihbfHeey2PBq07qVYPqFD5nr9XdAHWkcC3MEJBs+PmvTNnTw6X6O9eaXYSX5XiXRAkAl0nUElnqFAki9o5yj85wT4cZ3n1gKirX70Vno+7gPfTcfouZYwLBMmoxYZPgtqSxZq3arzobFi0o7pCo6rbOhAkEA0p7lT1MC2yl8ZIZ7g2Id1cilFf1Yj6gIJOivjtq943/pf5/NzKUE/jQ8fkf2V9sANnqEZlVnAwYYGYnsev0oUA==";
        byte[] keyBytes = Base64.decode(privateKeyMerchant.getBytes());
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return new String(decryptedData,"UTF-8");
    }
 
}
